import {nanoid} from "nanoid"
import {EventsEmit, EventsOnce} from "frontend/src/wailsjs/runtime";
import CryptoJS from 'crypto-js';

const event = "file"

export enum Type {
    Read = "read",
    Write = "write"
}

export interface Request<T = any> {
    channel: string
    type: Type
    payload: T
}

export interface ReadFileRequest {
    channel: string
    path: string
}

export interface ReadResponse {
    // base64
    Data: string
    Error?: string
}

export interface WriteFileRequest {
    channel: string
    path: string
    // base64
    data: string
}

export interface WriteResponse {
    Error?: string
}

export function writeFileWithRawData(path: string, rawData: Uint8Array | ArrayBufferLike | string) {
    return writeFileWithBlob(path, new Blob([rawData]))
}

export function writeFileWithBlob(path: string, rawData: Blob) {
    return new Promise<void | string>((resolve, reject) => {
        let fileReader = new FileReader()
        fileReader.addEventListener("load", (e) => {
            let rawBase64 = e.target!.result as string || ""
            let base64 = rawBase64.split(",", 2)[1]

            writeFileWithBase64(path,base64).then(resolve).catch(reject)
        })

        fileReader.addEventListener("error", () => {
            reject("数据编码 或 读取 失败")
        })

        fileReader.readAsDataURL(rawData)
    })
}

export function writeFileWithBase64(path: string, base64: string) {
    return new Promise<void | string>((resolve, reject) => {
        let channel = nanoid()
        EventsOnce(channel, (data: WriteResponse) => {
            if (data.Error) {
                reject(data.Error)
            } else {
                resolve()
            }
        })

        EventsEmit(event, JSON.stringify(<Request<WriteFileRequest>>{
            channel: channel,
            type: Type.Write,
            payload: {
                path: path,
                data: base64
            }
        }))
    })
}

export function readFileWithBinary(path){
    return new Promise((resolve,reject)=>{
        readFileWithText(path).then(data=>{
            let encoder = new TextEncoder()
            resolve(encoder.encode(data))
        }).catch(error=>{
            reject(error)
        })
    })
}

export function readFileWithText(path: string){
    return new Promise<string>((resolve, reject) => {
        let channel = nanoid()
        EventsOnce(channel, (data: ReadResponse) => {
            console.log(data)
            if (data.Error) {
                reject(data.Error)
            } else {
                resolve(CryptoJS.enc.Base64.parse(data.Data).toString(CryptoJS.enc.Utf8))
            }
        })

        EventsEmit(event, JSON.stringify(<Request<ReadFileRequest>>{
            channel: channel,
            type: Type.Read,
            payload: {
                path: path,
            }
        }))

    })
}

let file = {
    writeFileWithBase64,
    writeFileWithRawData,
    writeFileWithBlob,
    readFileWithText,
    readFileWithBinary
};

(window as any).file = file;
(window as any).CryptoJS = CryptoJS;
export default file